import { Injectable, OnModuleInit, Inject, forwardRef } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Cron } from './cron.entity';
import axios from 'axios';
import * as nodeCron from 'node-cron';
import { TaskService } from '../task/task.service';
import { Task } from '../task/task.entity';
import * as schedule from 'node-schedule';
import { LogService } from '../log/log.service';

@Injectable()
export class CronService implements OnModuleInit {
  private cronJobs: Map<number, any> = new Map();
  private taskList: Record<number, schedule.Job> = {}; // 存储所有定时任务

  constructor(
    @InjectRepository(Cron)
    private cronRepository: Repository<Cron>,
    @Inject(forwardRef(() => TaskService))
    private taskService: TaskService,
    private logService: LogService
  ) { }

  async onModuleInit() {
    // 启动时加载所有活跃的定时任务
    await this.loadActiveCrons();
    console.log('初始化定时任务调度器...');
    await this.getTaskAndRun();
  }

  async findAll(): Promise<Cron[]> {
    return this.cronRepository.find();
  }

  async findOne(id: number): Promise<Cron> {
    return this.cronRepository.findOne({ where: { id } });
  }

  async create(createCronDto: any): Promise<Cron> {
    const cron = new Cron();
    cron.robotId = createCronDto.robotId;
    cron.name = createCronDto.name;
    cron.content = createCronDto.content;
    cron.cronTime = createCronDto.cronTime;
    cron.isActive = createCronDto.isActive !== undefined ? createCronDto.isActive : true;

    const savedCron = await this.cronRepository.save(cron);

    // 如果定时任务是活跃的，立即启动它
    if (savedCron.isActive) {
      this.startCronJob(savedCron);
    }

    return savedCron;
  }

  async update(id: number, updateCronDto: any): Promise<Cron> {
    await this.cronRepository.update(id, updateCronDto);

    const updatedCron = await this.findOne(id);

    // 如果定时任务已经在运行，停止它
    if (this.cronJobs.has(id)) {
      this.stopCronJob(id);
    }

    // 如果更新后的定时任务是活跃的，重新启动它
    if (updatedCron.isActive) {
      this.startCronJob(updatedCron);
    }

    return updatedCron;
  }

  async remove(id: number): Promise<void> {
    // 如果定时任务正在运行，停止它
    if (this.cronJobs.has(id)) {
      this.stopCronJob(id);
    }

    await this.cronRepository.delete(id);
  }

  private async loadActiveCrons() {
    const activeCrons = await this.cronRepository.find({ where: { isActive: true } });

    for (const cron of activeCrons) {
      this.startCronJob(cron);
    }

    console.log(`Loaded ${activeCrons.length} active cron jobs`);
  }

  private startCronJob(cron: Cron) {
    try {
      // 使用node-cron创建定时任务
      const job = nodeCron.schedule(cron.cronTime, async () => {
        try {
          // 获取机器人信息
          const robot = await this.getRobotInfo(cron.robotId);

          if (!robot) {
            console.error(`Robot with ID ${cron.robotId} not found`);
            return;
          }

          // 发送消息到企业微信机器人
          await axios.post(robot.webhook, {
            msgtype: 'markdown',
            markdown: {
              content: cron.content
            }
          });

          console.log(`Cron job ${cron.id} (${cron.name}) executed successfully`);
        } catch (error) {
          console.error(`Error executing cron job ${cron.id} (${cron.name}):`, error);
        }
      });

      // 存储定时任务引用
      this.cronJobs.set(cron.id, job);
      console.log(`Started cron job ${cron.id} (${cron.name}) with schedule: ${cron.cronTime}`);
    } catch (error) {
      console.error(`Failed to start cron job ${cron.id} (${cron.name}):`, error);
    }
  }

  private stopCronJob(id: number) {
    const job = this.cronJobs.get(id);
    if (job) {
      job.stop();
      this.cronJobs.delete(id);
      console.log(`Stopped cron job ${id}`);
    }
  }

  private async getRobotInfo(robotId: number) {
    // 实现获取机器人信息的逻辑，可以通过依赖注入RobotService，或者直接访问数据库
    try {
      const repository = this.cronRepository.manager.getRepository('Robot');
      return repository.findOne({ where: { id: robotId } });
    } catch (error) {
      console.error(`Failed to get robot info for ID ${robotId}:`, error);
      return null;
    }
  }

  /**
   * 创建周期性任务
   */
  async createTask(id: number, cron: string, isWorkday: boolean = false) {
    // 检查任务是否已存在
    if (this.taskList[id]) {
      console.log(`任务ID：${id}，已存在，跳过创建`);
      return;
    }

    console.log(`创建定时任务：ID=${id}, CRON=${cron}, 工作日=${isWorkday}`);

    try {
      const task = schedule.scheduleJob(cron, async () => {
        // 过滤不满足工作日条件的执行
        if (isWorkday && !this.isWorkday()) {
          console.log(`任务ID：${id}，今天不是工作日，跳过执行`);
          return;
        }

        // 获取最新的任务信息
        const taskInfo = await this.taskService.findOne(id);
        if (!taskInfo || taskInfo.status !== '1') { // 检查任务是否有效
          console.log(`任务ID：${id}，状态无效，跳过执行`);
          return;
        }

        try {
          // 执行发送消息
          console.log(`执行定时任务：ID=${id}`);
          await this.taskService.sendTaskMessage(taskInfo);
          console.log(`任务ID：${id}，执行成功！`);
        } catch (error) {
          console.error(`任务ID：${id}，执行失败：`, error);
        }
      });

      this.taskList[id] = task;
      console.log(`任务ID：${id}，创建成功！`);
    } catch (error) {
      console.error(`创建定时任务失败，ID=${id}：`, error);
    }
  }

  /**
   * 创建一次性任务
   */
  async createOneTime(id: number, executeTime: Date) {
    // 检查任务是否已存在
    if (this.taskList[id]) {
      console.log(`一次性任务ID：${id}，已存在，跳过创建`);
      return;
    }

    // 计算当前时间到执行时间的毫秒数
    const now = new Date();
    const executeDate = new Date(executeTime);
    const delay = executeDate.getTime() - now.getTime();

    console.log(`创建一次性任务：ID=${id}, 执行时间=${executeDate.toISOString()}, 延迟=${delay}ms`);

    if (delay <= 0) {
      console.log(`任务ID：${id}，执行时间已过，立即执行`);

      // 获取任务信息
      const taskInfo = await this.taskService.findOne(id);
      if (!taskInfo) {
        console.error(`任务ID：${id} 不存在`);
        return;
      }

      try {
        // 立即执行
        await this.taskService.sendTaskMessage(taskInfo);
        console.log(`一次性任务ID：${id}，立即执行完成！`);

        // 更新任务状态为已完成
        await this.taskService.updateTask(id, { status: '2' });
      } catch (error) {
        console.error(`一次性任务ID：${id}，执行失败：`, error);
      }

      return;
    }

    try {
      // 使用 node-schedule 的 scheduleJob 方法创建一次性任务
      const task = schedule.scheduleJob(executeDate, async () => {
        console.log(`执行一次性任务：ID=${id}, 时间=${new Date().toISOString()}`);

        // 获取任务信息
        const taskInfo = await this.taskService.findOne(id);
        if (!taskInfo) {
          console.error(`任务ID：${id} 不存在或已被删除`);

          // 从任务列表中移除
          if (this.taskList[id]) {
            delete this.taskList[id];
          }
          return;
        }

        try {
          // 执行发送消息
          await this.taskService.sendTaskMessage(taskInfo);
          console.log(`一次性任务ID：${id}，执行成功！`);

          // 更新任务状态为已完成
          await this.taskService.updateTask(id, { status: '2' });

          // 从任务列表中移除
          delete this.taskList[id];
        } catch (error) {
          console.error(`一次性任务ID：${id}，执行失败：`, error);
        }
      });

      this.taskList[id] = task;
      console.log(`一次性任务ID：${id}，创建成功！将于 ${executeDate.toLocaleString()} 执行`);
    } catch (error) {
      console.error(`创建一次性任务失败，ID=${id}：`, error);
    }
  }

  /**
   * 取消任务
   */
  cancel(id: number) {
    if (this.taskList[id]) {
      console.log(`取消任务：ID=${id}`);
      this.taskList[id].cancel();
      delete this.taskList[id];
      console.log(`任务ID：${id}，取消成功！`);
      return true;
    }

    console.log(`任务ID：${id} 不存在，无需取消`);
    return false;
  }

  /**
   * 取消某个机器人的所有任务
   */
  async cancelRobotAll(robotId: number) {
    console.log(`取消机器人下的所有任务：robotId=${robotId}`);

    try {
      // 查询所有属于此机器人的任务
      const tasks = await this.taskService.findAll(robotId);
      console.log(`找到机器人 ${robotId} 下的 ${tasks.length} 个任务`);

      // 取消每个任务
      for (const task of tasks) {
        this.cancel(task.id);
      }

      return true;
    } catch (error) {
      console.error(`取消机器人任务失败，robotId=${robotId}：`, error);
      return false;
    }
  }

  /**
   * 初始化系统，查询所有任务并执行
   */
  async getTaskAndRun() {
    console.log('初始化定时任务...');

    // 清空当前任务列表
    for (const id in this.taskList) {
      this.cancel(Number(id));
    }

    try {
      // 查询所有状态为"已启用"的任务
      const tasks = await this.taskService.findAll();
      const activeTasks = tasks.filter(task => task.status === '1');

      console.log(`找到 ${activeTasks.length} 个有效任务需要调度`);

      // 为每个任务创建调度
      for (const task of activeTasks) {
        if (task.isOneTime) {
          // 一次性任务
          await this.createOneTime(task.id, task.executeTime);
        } else if (task.cron) {
          // 周期性任务
          await this.createTask(task.id, task.cron, task.isWorkday);
        }
      }

      console.log('定时任务初始化完成！');
      return activeTasks;
    } catch (error) {
      console.error('初始化定时任务失败：', error);
      return [];
    }
  }

  /**
   * 判断今天是否是工作日
   * 简单实现，仅判断是否是周末
   * 可以扩展为接入第三方API判断法定节假日
   */
  isWorkday(): boolean {
    const now = new Date();
    const day = now.getDay();
    // 0是周日，6是周六
    return day !== 0 && day !== 6;
  }
} 